package com.example.chat.view

import android.content.res.Configuration
import androidx.compose.foundation.*
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.text.BasicTextField
import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.draw.drawBehind
import androidx.compose.ui.focus.FocusRequester
import androidx.compose.ui.focus.focusRequester
import androidx.compose.ui.focus.onFocusChanged
import androidx.compose.ui.geometry.CornerRadius
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.geometry.Size
import androidx.compose.ui.graphics.drawscope.rotate
import androidx.compose.ui.platform.LocalTextInputService
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.input.ImeAction
import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.example.chat.R
import com.example.chat.model.Message
import com.example.chat.model.MessageStatus
import com.example.chat.model.Topic
import com.example.chat.model.UserMessage
import com.example.chat.navigation.NavigationController
import com.example.chat.viewmodel.TopicDetailCommands
import com.example.chat.viewmodel.TopicDetailState
import com.example.featuresdk.model.*
import com.example.featuresdk.theme.DemoTheme
import com.example.featuresdk.theme.button
import com.example.featuresdk.theme.myMessageBackground
import com.example.featuresdk.theme.otherMessageBackground
import com.example.featuresdk.view.*
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.launch
import java.sql.Timestamp

@ExperimentalFoundationApi
@Composable
fun TopicDetailScreen(uiState: TopicDetailState, uiConstraints: LayoutConstraints,commands: TopicDetailCommands){
    val messages by uiState.messages.collectAsState(initial = emptyList())
    val topic by uiState.topic.collectAsState(initial = Topic())

    FullScreen(uiConstraints) {

        AppHeaderContainer(uiConstraints.appHeaderBarHeightDp) {
            HeaderBackFeatureEntry{
                NavigationController.instance.back()
            }
            AppHeaderTitle("${topic.title}", uiConstraints.headerWidthDp)
            FeatureEntry("...", onClick = {
//                NavigationController.navigate(Screen.TopicSetting, topic.id.toString())
                commands.openTopicSetting(topic.id!!)
            })
        }

        AppBodyView(bodyHeightDp = {
            if (uiState.messageTypeSelectorVisible.value)
                uiConstraints.activeChatWindowHeightDp.dp
            else
                uiConstraints.defaultChatWindowHeightDp.dp},
            backgroundColor = DemoTheme.colors.primary) {

            MessageListView(messages, uiConstraints, commands)
        }

        AppBottomView{
            Column {
                AppRowContainer(uiConstraints.appBottomBarHeightDp.dp) {
                    ChatContentTypeSelector(commands, uiState, uiConstraints)
                }

                ChatContentSelector(commands, uiState, uiConstraints)
            }
        }
    }
}

@Composable
fun MessageListView(userMessages: List<UserMessage>, uiConstraints: LayoutConstraints, commands: TopicDetailCommands, modifier:Modifier = Modifier.fillMaxSize()) {

    val messageListState = rememberLazyListState()
    val coroutineScope = rememberCoroutineScope()

    LazyColumn (modifier = modifier.background(DemoTheme.colors.primary),
        verticalArrangement = Arrangement.spacedBy(4.dp),
        state = messageListState) {

        items(userMessages, { it -> it.message.id!!}){ it ->
            if(it.message.sender == User.ME.id) {
                MyMessageView(it, uiConstraints, commands)
            }else{
                ReceivedMessageView(it, uiConstraints, commands)
            }
        }
    }

    //auto scroll to last message
    LaunchedEffect(userMessages){
        snapshotFlow { userMessages.lastIndex }
            .distinctUntilChanged()
            .collect { lastIndex ->
                coroutineScope.launch {
                    messageListState.animateScrollToItem(lastIndex)
                }
            }
    }
}

@Composable
fun MyMessageView(userMessage: UserMessage, uiConstraints: LayoutConstraints, commands: TopicDetailCommands){

    Row(horizontalArrangement = Arrangement.End,
        verticalAlignment = Alignment.Top
    ) {

        Spacer(modifier = Modifier.width(uiConstraints.userIconWidth.dp))

        Box(modifier = Modifier.width(uiConstraints.messageContentWidth.dp)
            ,contentAlignment = Alignment.TopEnd){

            val messageBackground = DemoTheme.colors.myMessageBackground

            Box(modifier = Modifier
                .heightIn(40.dp)
                .widthIn(30.dp)
                .drawBehind {
                    drawRoundRect(messageBackground, cornerRadius = CornerRadius(10f, 10f))
                    rotate(45f, Offset(this.size.width, 60f)) {
                        drawRect(
                            messageBackground,
                            Offset(this.size.width - 30, 30f), size = Size(20f, 20f)
                        )
                    }
                }){

                Column {
                    val message = userMessage.message
                    message.text?.let {
                        Text(text = "${message.text}",
                            modifier = Modifier.padding(6.dp),
                            overflow = TextOverflow.Visible,
                            color = contentColorFor(DemoTheme.colors.secondary),
                            style = DemoTheme.typography.messageSent)
                    }

                    message.image?.let {
                        //size = 100.dp
                        Image(painter = painterResource(it),
                            contentDescription = "",
                            modifier = Modifier.size(100.dp))
                    }
                }
            }

        }

        MessageParticipant(userMessage.sender, commands)
    }
}

@Composable
fun ReceivedMessageView(userMessage: UserMessage, uiConstraints: LayoutConstraints, commands: TopicDetailCommands){

    Row(horizontalArrangement = Arrangement.Start,
        verticalAlignment = Alignment.Top) {

        MessageParticipant(userMessage.sender, commands)

        Box(modifier = Modifier.width(uiConstraints.messageContentWidth.dp)
            ,contentAlignment = Alignment.TopStart){

            val otherMessageBackground = DemoTheme.colors.otherMessageBackground
            Box(modifier = Modifier
                .heightIn(40.dp)
                .widthIn(30.dp)
                .drawBehind {
                    rotate(45f, Offset(0f, 60f)) {
                        drawRect(
                            otherMessageBackground,
                            Offset(-30f, 30f), size = Size(20f, 20f)
                        )
                    }
                    drawRoundRect(otherMessageBackground, cornerRadius = CornerRadius(10f, 10f))
                }) {

                Column{
                    val message = userMessage.message
                    message.text?.let {
                        Text(
                            text = "${message.text}",
                            modifier = Modifier.padding(6.dp),
                            color = contentColorFor(DemoTheme.colors.secondary),
                            overflow = TextOverflow.Visible,
                            style = DemoTheme.typography.messageReceived
                        )
                    }

                    message.image?.let {
                        Image(
                            painter = painterResource(it),
                            contentDescription = "",
                            modifier = Modifier
                                .width(100.dp)
                                .height(100.dp)
                        )
                    }
                }
            }
        }
    }
}

@Composable
fun MessageParticipant(sender: User, commands: TopicDetailCommands){
    Spacer(modifier = Modifier.width(5.dp))

    Image(painter = painterResource(id = sender.icon),
        contentDescription = sender.nickname,
        modifier = Modifier
            .size(40.dp)
            .clip(RoundedCornerShape(4.dp))
            .clickable {
//                NavigationController.instance.navigate(Screen.ContactDetailExternal,sender.id.toString())
                commands.openContactDetail(sender.id!!)
            })

    Spacer(modifier = Modifier.width(5.dp))
}

@ExperimentalFoundationApi
@Composable
fun ChatContentSelector(commands: TopicDetailCommands, uiState: TopicDetailState, uiConstraints: LayoutConstraints) {

    when(uiState.messageType.value){
        MessageType.Voice -> {
            uiState.messageTypeSelectorVisible.value = false
        }
        MessageType.Text -> {
            //TODO: set focus to text input field to show software keyboard
        }
        MessageType.Emoji -> {
            EmojiDashboard(commands,uiState, uiConstraints)
            uiState.messageTypeSelectorVisible.value = true
        }
        MessageType.Photo -> {
            Text(text = "*************Photo************")
            //TODO: shwo photo selector in new screen
        }
        MessageType.None -> {
            uiState.messageTypeSelectorVisible.value = false
        }
        MessageType.Others -> {
            uiState.messageTypeSelectorVisible.value = true
            MoreContentTypeSelector(commands, uiState)
        }
    }
}

@Composable
fun ChatContentTypeSelector(commands: TopicDetailCommands, uiState: TopicDetailState, uiConstraints: LayoutConstraints) {

    Spacer(modifier = Modifier.width(6.dp))

    if (uiState.messageType.value != MessageType.Voice) {
        ChatTypeFeatureEntry(icon = R.drawable.ic_voice, onClick = {
            uiState.messageType.value = MessageType.Voice
        })
    } else {
        ChatTypeFeatureEntry(icon = R.drawable.ic_keyboard, onClick = {
            uiState.messageType.value = MessageType.Text
        })
    }

    Spacer(modifier = Modifier.width(2.dp))

    if (uiState.messageType.value == MessageType.Voice) {
        OutlinedButton(modifier = Modifier
            .width(uiConstraints.defaultTextFieldWidthDp.dp)
            .height(30.dp)
            .background(DemoTheme.colors.secondary)
            .clip(RoundedCornerShape(4.dp)),
            contentPadding = PaddingValues(0.dp)
            ,onClick = {
                //TODO: launch the voice record
            }) {
            Text(text = "Click and Say",
                color = contentColorFor(DemoTheme.colors.secondary),
                style = DemoTheme.typography.button)
        }
    } else {
        BasicTextField(value = uiState.chatContent.value,
            onValueChange = { uiState.chatContent.value = it },
            modifier = Modifier
                .width(if (uiState.chatContent.value.isBlank()) {
                        uiConstraints.defaultTextFieldWidthDp.dp
                    } else {
                        uiConstraints.activeTextFieldWidthDp.dp
                    })
                .height(30.dp)
                .background(DemoTheme.colors.secondary)
                .clip(RoundedCornerShape(4.dp))
                .focusable(enabled = true)
                .focusRequester(FocusRequester.Default)
                .onFocusChanged {
                    if (it.isFocused) {
                        uiState.messageTypeSelectorVisible.value = true
                        uiState.messageType.value = MessageType.Text
                    } else {
                        uiState.messageTypeSelectorVisible.value = false
                    }
                },
            textStyle = TextStyle(color = contentColorFor(DemoTheme.colors.secondary)),
            keyboardOptions = KeyboardOptions(
                keyboardType = KeyboardType.Text,
                imeAction = ImeAction.Send
            ),
            keyboardActions = KeyboardActions(
                onSend = {
                    commands.sendMessage()
                }
            ),
            singleLine = true
        )
    }

    Spacer(modifier = Modifier.width(2.dp))
    val inputService = LocalTextInputService.current
    if (uiState.messageType.value == MessageType.Emoji) {
        ChatTypeFeatureEntry(icon = R.drawable.ic_keyboard, onClick = {
            uiState.messageType.value = MessageType.Text
            inputService?.showSoftwareKeyboard()
        })
    }else{
        ChatTypeFeatureEntry(icon = R.drawable.ic_emoji, onClick = {
            uiState.messageType.value = MessageType.Emoji
            inputService?.hideSoftwareKeyboard()
        })
    }

    Spacer(modifier = Modifier.width(2.dp))

    if(uiState.chatContent.value.isBlank()) {
        ChatTypeFeatureEntry(icon = R.drawable.ic_add, onClick = {
            uiState.messageType.value = MessageType.Others
        })
    }else{
        Button(onClick = { commands.sendMessage() },
            modifier = Modifier
                .height(30.dp)
                .width(65.dp)
                .padding(0.dp),
            contentPadding = PaddingValues(0.dp),
            colors = ButtonDefaults.buttonColors(backgroundColor = DemoTheme.colors.button)){
            Text("Send", style = DemoTheme.typography.button)
        }
    }

    Spacer(modifier = Modifier.width(6.dp))
}

@Composable
inline fun ChatTypeFeatureEntry(icon: Int, crossinline onClick:()->Unit) {
    Image(painter = painterResource(icon),
        contentDescription = "",
        modifier = Modifier
            .width(30.dp)
            .height(30.dp)
            .clickable { onClick() }
    )
}


@Composable
fun MoreContentTypeSelector(commands: TopicDetailCommands, uiState: TopicDetailState) {


}


@ExperimentalMaterialApi
@Preview(showBackground = true)
@Composable
fun PreviewTopicDetailScreenLight()
{
    DemoTheme(darkTheme = false) {
        PreviewTopicDetailScreen()
    }
}

@ExperimentalMaterialApi
@Preview(showBackground = true)
@Composable
fun PreviewTopicDetailScreenDark()
{
    DemoTheme(darkTheme = true) {
        PreviewTopicDetailScreen()
    }
}

@ExperimentalMaterialApi
@Composable
fun PreviewTopicDetailScreen(){

    val user = User(2,"Avatar", R.drawable.ic_user)
    val message1 = Message(1000,1000, User.ME.id!!,"Hello World",null, MessageStatus.New, Timestamp(System.currentTimeMillis()))
    val message2 = Message(1001,1000, user.id!!,"Great, nice message!",null,
        MessageStatus.New, Timestamp(System.currentTimeMillis()))
    val userMessages = listOf(UserMessage(message1,User.ME), UserMessage(message2,user))

    val uiConstraints = LayoutConstraints().apply {
        init(Configuration().apply {
            this.screenHeightDp = 150
            this.screenWidthDp = 392
        })
    }

    val commands = object: TopicDetailCommands{ }

    Column {
        val modifier = Modifier.size(uiConstraints.screenWithDp.dp, uiConstraints.screenHeightDp.dp)
        MessageListView(userMessages, uiConstraints, commands,modifier)

        val modifier2 = Modifier.size(uiConstraints.screenWithDp.dp, uiConstraints.appBottomBarHeightDp.dp)
        AppBottomView(modifier2) {
            AppRowContainer(uiConstraints.appBottomBarHeightDp.dp) {
                ChatContentTypeSelector(
                    commands,
                    TopicDetailState().apply {
                        this.messageTypeSelectorVisible.value = true
                        this.messageType.value = MessageType.Text
                    }, uiConstraints
                )
            }
        }

        AppBottomView(modifier2) {
            AppRowContainer(uiConstraints.appBottomBarHeightDp.dp) {
                ChatContentTypeSelector(
                    commands,
                    TopicDetailState().apply {
                        this.messageTypeSelectorVisible.value = true
                        this.messageType.value = MessageType.Voice
                    }, uiConstraints
                )
            }
        }

        AppBottomView(modifier2) {
            AppRowContainer(uiConstraints.appBottomBarHeightDp.dp) {
                ChatContentTypeSelector(
                    commands,
                    TopicDetailState().apply {
                        this.messageTypeSelectorVisible.value = true
                        this.messageType.value = MessageType.Emoji
                    }, uiConstraints
                )
            }
        }

        AppBottomView(modifier2) {
            AppRowContainer(uiConstraints.appBottomBarHeightDp.dp) {
                ChatContentTypeSelector(
                    commands,
                    TopicDetailState().apply {
                        this.messageTypeSelectorVisible.value = true
                        this.messageType.value = MessageType.Text
                        this.chatContent.value = "Hello"
                    }, uiConstraints
                )
            }
        }
    }
}